#include <StreamSummary.hpp>
#include "common/DepLibUV.hpp"
#include <limits>

template<typename T>
static bool lowerThan(const T lhs, const T rhs);

template<typename T>
static bool higherThan(const T lhs, const T rhs);

bool StreamSummary::IsLastProcessMoreThan500ms() {
	uint64_t now = DepLibUV::GetTime();
	if (0 == this->lastProcessTime) {
		this->lastProcessTime = now;
		return false;
	}
	uint64_t dis = now - this->lastProcessTime;
	this->lastProcessTime = now;
	
	return dis > WAIT_SEQ_TIME_MS;
}

void StreamSummary::CheckFirstFrame(uint16_t seq) {
  if (firstPacket) {
	currentSeq = seq;
	firstPacket = false;
  }
}

bool StreamSummary::IsLowerThanCurrentSeq(uint16_t seq) {
	return ::lowerThan<uint16_t>(seq, this->currentSeq);
}

bool StreamSummary::IsHigherThanCurrentSeq(uint16_t seq) {
	return ::higherThan<uint16_t>(seq, currentSeq);
}

bool StreamSummary::IsWantSeq(uint16_t seq) {
	return seq == currentSeq;
}

uint16_t StreamSummary::GetLostSeqSize(uint16_t seq) {
	if (seq <= this->currentSeq) {
		return 0;
	}
	return seq - this->currentSeq - 1;
}

void StreamSummary::SetNextCurrentSeq(uint16_t seq) {
	this->currentSeq = seq + 1;
}

bool StreamSummary::IsHigherThanPreviousFrameTime(uint32_t curFrameTime) {
	bool ret = ::higherThan<uint32_t>(curFrameTime, this->frameTime);
	if (ret) {
		printf("IsHigherThanPreviousFrameTime true,curFrameTime:%u, frameTime:%u\n", curFrameTime, this->frameTime);
	}
	return ret;
}

template<typename T>
static bool lowerThan(const T lhs, const T rhs)	{
	static T MaxValue = std::numeric_limits<T>::max();
	bool isLower = ((rhs > lhs) && (rhs - lhs <= MaxValue / 2));
	if (isLower) {
		return true;
	}
	bool isHighButTooLong = ((lhs > rhs) && (lhs - rhs > MaxValue / 2));
	return isHighButTooLong;
}

template<typename T>
static bool higherThan(const T lhs, const T rhs) {
	static T MaxValue = std::numeric_limits<T>::max();
	
	bool isHigherThan = (lhs > rhs) && (lhs - rhs <= MaxValue / 2);
	if (isHigherThan) {
		return true;
	}
	
	bool isLowerThanTooLong = (rhs > lhs) && (rhs - lhs > MaxValue / 2);
	 return isLowerThanTooLong;
}